package cn.xuqiudong.attachment.service;

import cn.xuqiudong.attachment.annotation.AttachmentFlag;
import cn.xuqiudong.attachment.autoconfigure.AttachmentProperties;
import cn.xuqiudong.attachment.dao.BaseAttachmentDao;
import cn.xuqiudong.attachment.dao.BaseAttachmentRelationDao;
import cn.xuqiudong.attachment.model.AttachmentFetchResult;
import cn.xuqiudong.attachment.model.AttachmentRelation;
import cn.xuqiudong.attachment.util.AttachmentFetchByAnnotationUtil;
import cn.xuqiudong.common.base.model.BaseEntity;
import cn.xuqiudong.common.base.service.AttachmentStatusOperationServiceI;
import cn.xuqiudong.common.util.collections.CalcDiffCollection;
import cn.xuqiudong.common.util.reflect.ReflectionUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * TODO  兼容作为客户端时候的处理
 * 说明 :  提供对附件状态操作的service
 * @author Vic.xu
 * @since  2020年9月21日上午11:23:45
 */
@Service
public class AttachmentStatusOperationService implements AttachmentStatusOperationServiceI {

    private static final Logger logger = LoggerFactory.getLogger(AttachmentStatusOperationService.class);

    @Autowired
    private AttachmentProperties attachmentProperties;

    @Autowired(required = false)
    private BaseAttachmentDao attachmentDao;

    @Autowired(required = false)
    private BaseAttachmentRelationDao attachmentRelationDao;

    @Autowired(required = false)
    private AttachmentClientService attachmentClientService;

    /**
     * 新增对象中的全部附件
     */
    @Override
    public <T extends BaseEntity> boolean addAttachmentFromObj(T t) {
        AttachmentFetchResult result = AttachmentFetchByAnnotationUtil.fetchAttachmentInfoFromObject(t);
        //新增附件
        updateTemporary(false, result.getIdList());
        //  新增附件关系
        attachmentRelationDao.batchInsert(result.getRelationList());
        return true;
    }

    /**
     * 删除对象中的附件
     */
    @Override
    public <T extends BaseEntity> void deleteAttachmentFromObj(T t) {
        AttachmentFetchResult result = AttachmentFetchByAnnotationUtil.fetchAttachmentInfoFromObject(t);
        // 删除附件
        updateTemporary(true, result.getIdList());
        //删除关系
        attachmentRelationDao.delete(String.valueOf(t.getId()), AttachmentFetchByAnnotationUtil.getRelationDesc(t.getClass()));
    }

    /**
     * 批量删除附件
     */
    @Override
    public <T extends BaseEntity> void deleteAttachmentFromObj(List<T> ts) {
        if (ts == null) {
            return;
        }
        //全部要删除的附件id
        List<Integer> idList = new ArrayList<>();
        //全部要删除的关系id
        List<Integer> relationIdList = new ArrayList<>();
        for (T t : ts) {
            AttachmentFetchResult result = AttachmentFetchByAnnotationUtil.fetchAttachmentInfoFromObject(t);
            idList.addAll(result.getIdList());
            relationIdList.addAll(result.getRelationIdList());
        }
        updateTemporary(true, idList);
        attachmentRelationDao.delete(relationIdList.toArray(new Integer[0]));
    }

    /**
     * 对比对象修改前后的附件 分别做新增和删除处理
     */
    @Override
    public <T extends BaseEntity> void handleOldAndNowAttachment(T old, T now) {
        // 提取出当前对象和数据库中对象的附件信息
        AttachmentFetchResult oldResult = AttachmentFetchByAnnotationUtil.fetchAttachmentInfoFromObject(old);
        AttachmentFetchResult nowResult = AttachmentFetchByAnnotationUtil.fetchAttachmentInfoFromObject(now);
        //处理附件
        CalcDiffCollection<Integer> idDiff = CalcDiffCollection.instance(oldResult.getIdList(), nowResult.getIdList());
        updateTemporary(true, idDiff.getOnlyInOld());
        updateTemporary(false, idDiff.getOnlyInNew());

        //处理关系， 新增的关系没有id
        //  先处理新增的关系。即没有id的关系
        List<AttachmentRelation> relationList = nowResult.getRelationList();
        List<AttachmentRelation> onlyNeedAdd = relationList.stream().filter(r -> r.getId() == null).collect(Collectors.toList());
        attachmentRelationDao.batchInsert(onlyNeedAdd);
        // 再处理 删除的关系
        CalcDiffCollection<Integer> relationIdDiff = CalcDiffCollection.instance(oldResult.getRelationIdList(), nowResult.getRelationIdList());
        List<Integer> onlyInOld = relationIdDiff.getOnlyInOld();
        attachmentRelationDao.delete(onlyInOld.toArray(new Integer[0]));

    }

    /**
     * 查询附件关系 并设置到实体中
     * @param entity Object
     */
    @Override
    public <T extends BaseEntity> void fillAttachmentInfo(T entity) {
        if (entity == null) {
            return;
        }
        Integer id = entity.getId();
        if (id == null || id.intValue() < 1) {
            return;
        }
        try {
            Class<?> clazz = entity.getClass();
            //实体描述
            String relationDesc = AttachmentFetchByAnnotationUtil.getRelationDesc(clazz);
            //可向上遍历父类
            for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    if (!field.isAnnotationPresent(AttachmentFlag.class)) {
                        continue;
                    }
                    AttachmentFlag flag = field.getAnnotation(AttachmentFlag.class);
                    switch (flag.value()) {
                        case RELATION:
                            String column = AttachmentFetchByAnnotationUtil.getColumn(flag, field);
                            List<AttachmentRelation> list = attachmentRelationDao.attachmentRelations(String.valueOf(id), relationDesc, column);
                            if (CollectionUtils.isEmpty(list)) {
                                break;
                            }
                            //判断是否是list
                            if (List.class.isAssignableFrom(field.getType())) {
                                ReflectionUtils.setFieldValue(entity, field.getName(), list);
                            } else {
                                ReflectionUtils.setFieldValue(entity, field.getName(), list.get(0));
                            }
                            break;
                        case SIGN:
                        case SIGNS:
                        case CONTENT:
                        default:
                            //其他类型暂时不填充
                            break;
                    }
                }


            }
        } catch (Exception e) {
            logger.error(ExceptionUtils.getStackTrace(e));
        }
    }

    /* *************************************************************************************************** */


    /** 修改附件状态 */
    public void updateTemporary(boolean temporary, List<Integer> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return;
        }
        // 如果是客户端则调用SDK，否则直接操作数据库
        if (isClient()) {
            attachmentClientService.updateTemporary(temporary, ids.toArray(new Integer[0]));
        } else {
            String idsStr = ids.stream().map(String::valueOf).collect(Collectors.joining(","));
            attachmentDao.updateTemporary(idsStr, temporary);
        }

    }

    /**
     * 当前是否是附件客户端
     *
     * @return if client
     */
    private boolean isClient() {
        Integer type = attachmentProperties.getType();
        return type != null && 2 == type;

    }

}
